# -*- coding: utf-8 -*-
import datetime
import json
import os
from base64 import encodebytes
from urllib.parse import quote_plus, parse_qs

from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django_redis import get_redis_connection

from utils.alipay import AliPay
from utils.encrypt import uid
from web import models


def index(request):
    return render(request, 'index.html')


def price(request):
    """套餐"""

    policy_list = models.PricePolicy.objects.filter(category=2)

    return render(request, 'price.html', {'policy_list': policy_list})


def payment(request, policy_id):
    """支付"""

    # 1. 价格策略
    policy_obj = models.PricePolicy.objects.filter(id=policy_id, category=2).first()
    if not policy_obj:
        return redirect('web:price')

    # 2. 购买数量
    number = request.GET.get('number', '')
    if not number or not number.isdecimal():
        return redirect('web:price')

    number = int(number)
    if number < 1:
        return redirect('web:price')

    # 3. 原价
    origin_price = number * policy_obj.price

    # 4. 优惠 抵扣
    balance = 0
    _obj = None
    if request.tracer.price_policy.category == 2:
        # 获取已有订单，总费用，开始，结束时间，剩余天数 =》 抵抗钱数
        _obj = models.Transaction.objects.filter(user=request.tracer.user, status=2).order_by('-id').first()
        # 总时间
        total_timedelta = _obj.end_time - _obj.start_time
        # 剩余时间
        balance_timedelta = _obj.end_time - datetime.datetime.now()
        if total_timedelta.days == balance_timedelta.days:
            # 刚买就还套餐，即同一天
            balance = _obj.price / total_timedelta.days * (balance_timedelta.days - 1)
        else:
            balance = _obj.price / total_timedelta.days * balance_timedelta.days

    if balance >= origin_price:
        return redirect('web:price')

    context = {
        'policy_id': policy_obj.id,
        'number': number,
        'origin_price': origin_price,
        'balance': round(balance, 2),  # 保留两位小数
        'total_price': origin_price - round(balance, 2)
    }

    # 缓存数据
    conn = get_redis_connection()
    key = 'payment_{}'.format(request.tracer.user.phone)
    conn.set(key, json.dumps(context), ex=60 * 30)

    context['policy_obj'] = policy_obj
    context['transaction'] = _obj

    return render(request, 'payment.html', context)


def pay(request):
    """支付"""

    conn = get_redis_connection()
    key = 'payment_{}'.format(request.tracer.user.phone)
    context_string = conn.get(key)

    if not context_string:
        return redirect('web:price')

    context = json.loads(context_string.decode('utf-8'))

    # 1. 生成订单
    order_id = uid(request.tracer.user.phone)
    total_price = context['total_price']
    models.Transaction.objects.create(
        status=1,
        order_num=order_id,
        user=request.tracer.user,
        price_policy_id=context['policy_id'],
        count=context['number'],
        price=total_price
    )

    # # 2. 支付宝支付
    # # 2.1 参数
    # params = {
    #     'app_id': settings.PAY_APP_ID,
    #     'method': settings.PAY_APP_METHOD,
    #     'format': 'JSON',
    #     'return_url': 'http://127.0.0.1:8001/pay/notify/',  # 支付成功后跳转的地址
    #     'notify_url': 'http://127.0.0.1:8001/pay/notify/',  # 支付成功后，往此地址发送一个POST请求
    #     'charset': 'utf-8',
    #     'sign_type': 'RSA2',
    #     'timestamp': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
    #     'version': '1.0',
    #     'biz_content': json.dumps({
    #         'out_trade_no': order_id,
    #         'product_code': 'FAST_INSTANT_TRADE_PAY',
    #         'total_amount': total_price,
    #         'subject': 'ydc',
    #     },
    #         separators=(',', ':')  # 在这些后面不加空格
    #     )
    # }
    #
    # # 2.2 构造待签名的数据: 对参数排序后拼接
    # unsigned_string = '&'.join(['{0}={1}'.format(k, params[k]) for k in sorted(params)])
    #
    # # 2.3 签名
    # private_key = RSA.importKey(open(os.path.join(settings.BASE_DIR + '\\files\\应用私钥2048.txt')).read())
    # signer = PKCS1_v1_5.new(private_key)
    # signature = signer.sign(SHA256.new(unsigned_string.encode('utf-8')))
    #
    # # 2.4签名后，base68表面，转成字符串，并去除\n
    # sign_string = encodebytes(signature).decode('utf-8').replace('\n', '')
    #
    # # 2.5 拼接到请求参数中
    # result = '&'.join(['{0}={1}'.format(k, quote_plus(params[k])) for k in sorted(params)])
    # result = result + '&sign=' + quote_plus(sign_string)
    #
    # ali_pay_url = '{}?{}'.format(settings.PAY_APP_GATEWAY, result)

    alipay = AliPay(
        app_id=settings.ALI_APP_ID,
        app_notify_url=settings.ALI_NOTIFY_URL,
        app_return_url=settings.ALI_RETURN_URL,
        app_pri_key_path=settings.ALI_PRI_KEY_PATH,
        app_pub_key_path=settings.ALI_PUB_KEY_PATH,
    )

    query_params = alipay.direct_pay(
        subject='ydc',
        out_trade_no=order_id,
        total_amount=total_price
    )
    ali_pay_url = '{}?{}'.format(settings.ALI_GATEWAY, query_params)

    return redirect(ali_pay_url)


def pay_notify(request):
    """支付宝支付成功回调函数"""

    alipay = AliPay(
        app_id=settings.ALI_APP_ID,
        app_notify_url=settings.ALI_NOTIFY_URL,
        app_return_url=settings.ALI_RETURN_URL,
        app_pri_key_path=settings.ALI_PRI_KEY_PATH,
        app_pub_key_path=settings.ALI_PUB_KEY_PATH,
    )

    if request.method == 'GET':
        # 跳转 不更新订单状态
        params = request.GET.dict()
        sign = params.pop('sign', None)  # 剔除
        status = alipay.verify(params, sign)
        if status:
            return HttpResponse("支付完成")
        return HttpResponse("支付失败")

    body_str = request.body.decode('utf-8')
    post_data = parse_qs(body_str)

    post_dict = {}
    for k, v in post_data.items():
        post_dict[k] = v[0]

    sign = post_dict.pop('sign', None)
    status = alipay.verify(post_dict, sign)
    if status:
        current_datatiem = datetime.datetime.now()
        out_trade_no = post_dict['out_trade_no']
        _obj = models.Transaction.objects.filter(order_num=out_trade_no).first()
        _obj.status = 2
        _obj.start_time = current_datatiem
        _obj.end_time = current_datatiem + datetime.timedelta(days=365 * _obj.count)
        _obj.save()

    # 相关状态完成后，需返回success给支付宝api
    return HttpResponse("success")
